package com.flybutter.usagelab.service

import android.app.Service
import android.app.usage.UsageEvents
import android.app.usage.UsageStats
import android.app.usage.UsageStatsManager
import android.content.Context
import com.flybutter.usagelab.broadcast.BatteryChangerReceiver
import com.flybutter.usagelab.broadcast.ScreenChangeReceiver
import android.content.Intent
import android.os.IBinder
import android.content.IntentFilter
import android.util.Log
import com.flybutter.usagelab.repository.AppDatabase
import com.flybutter.usagelab.repository.UsageInfo
import com.flybutter.usagelab.repository.getAppDataBase
import com.flybutter.usagelab.utils.executorService
import com.flybutter.usagelab.utils.getFiled
import java.time.Instant
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.*
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledThreadPoolExecutor
import java.util.concurrent.TimeUnit

fun queryUsageData(context: Context, startTime: Long, endTime: Long): List<UsageInfo> {
    val sm = context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
    val usageEvents = sm.queryEvents(startTime, endTime)
    val eventsMap = mutableMapOf<String, MutableList<UsageEvents.Event>>()
    val allEvents = mutableListOf<UsageEvents.Event>()
    while (usageEvents.hasNextEvent()) {
        val event = UsageEvents.Event()
        allEvents.add(event)
        usageEvents.getNextEvent(event)
        eventsMap.getOrDefault(event.packageName, mutableListOf()).add(event)
    }
    //统计启动时间
    var startTime = allEvents[0].timeStamp
    val list = mutableListOf<UsageInfo>()
    for (i in 1 until allEvents.size) {
        val event = allEvents[i];
        val lastEvent = allEvents[i - 1]

        if (lastEvent.packageName != event.packageName && event.eventType == UsageEvents.Event.ACTIVITY_RESUMED) {
            Log.d("queryUsageData", "queryUsageData: 启动了")
            val usageInfo = UsageInfo(
                UUID.randomUUID().toString(),
                lastEvent.packageName,
                1,
                startTime,
                lastEvent.timeStamp,
                lastEvent.timeStamp - startTime
            )
            list.add(usageInfo)
            startTime = event.timeStamp
        }
    }
    return list
}

/**
 * 负责监听数据，收集并写入到数据库
 */
class MonitorService : Service() {
    val TAG = MonitorService::class.simpleName
    val INTERVAL: Long = 1000 * 5

    private val batteryChangerReceiver: BatteryChangerReceiver
    private val screenChangeReceiver: ScreenChangeReceiver
    private val scheduledExecutorService: ScheduledThreadPoolExecutor
    private val ioExecutorService: ExecutorService

    @Volatile
    lateinit var baseUsageStatsMap: MutableMap<String, UsageStats>

    val lastUsageStatsMap = mutableMapOf<String,UsageStats>()

    init {
        batteryChangerReceiver = BatteryChangerReceiver()
        screenChangeReceiver = ScreenChangeReceiver()
        ioExecutorService = Executors.newSingleThreadExecutor()
        scheduledExecutorService = ScheduledThreadPoolExecutor(2)
    }

    override fun onCreate() {
        registerBroadcastReceiver()
        startMonitorUsage()
    }

    override fun onBind(intent: Intent): IBinder? {
        return null
    }

    fun startMonitorUsage(){
        val sm = getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
        val startTime = LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli()
        baseUsageStatsMap = sm.queryAndAggregateUsageStats(
            LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli(),
            System.currentTimeMillis()
        )
        scheduledExecutorService.scheduleAtFixedRate({
            monitorUsage(sm)
        },INTERVAL,INTERVAL,TimeUnit.MILLISECONDS)
    }

    /**
     * UsageStats是通过事件来更新数据的，如果一直在使用一个Activity，则各项数据都不会变
     * 所以配置event和UsageStats一起来确定时间
     * 一个app在使用时，lastUsedTime，lastTimeStamp和totalTimeUsed
     */
    fun monitorUsage(sm: UsageStatsManager){
        val startTime = LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli()
        val endTime = System.currentTimeMillis() - 5*1000
        val list = sm.queryAndAggregateUsageStats(startTime,endTime)
        val events = sm.queryEvents(startTime,endTime)
        val allEvents = mutableListOf<UsageEvents.Event>()
        var runApp = ""
        while (events.hasNextEvent()){
            val event = UsageEvents.Event()
            events.getNextEvent(event)
            allEvents.add(event)
        }
        for (i in 1 until allEvents.size){
            val le = allEvents[i-1]
            val e = allEvents[i]
            if (le.packageName != e.packageName && e.eventType == UsageEvents.Event.ACTIVITY_RESUMED){
                runApp = e.packageName
            }
        }

        list.values.forEach { usageStats ->
            val baseCount = baseUsageStatsMap[usageStats.packageName]?.getFiled<Int>("appLaunchCount") ?:0
            val currentCount = usageStats.getFiled<Int>("appLaunchCount") ?:0
            val baseUsageStats = baseUsageStatsMap[usageStats.packageName]
            val lastUsageStats = lastUsageStatsMap[usageStats.packageName]
            //避免有新安装的应用
            if (baseUsageStats == null){
                baseUsageStatsMap[usageStats.packageName] = usageStats
                return@forEach
            }
            val runTimeChange = usageStats.totalTimeInForeground - baseUsageStatsMap[usageStats.packageName]!!.totalTimeInForeground
            val list = mutableListOf<UsageInfo>()
            if(runTimeChange > 0){
                Log.d(TAG, "monitorUsage: $runApp")
                //避免因为切换activity导致的分段
                if(lastUsageStats != null &&
                    ((usageStats.lastTimeUsed - runTimeChange) - lastUsageStats.lastTimeStamp < 1000)
                    && runApp == usageStats.packageName
                ){
                    lastUsageStatsMap[usageStats.packageName] = usageStats
                    return@forEach
                }
                val info = UsageInfo(UUID.randomUUID().toString(),
                    usageStats.packageName,
                    currentCount - baseCount,
                    usageStats.lastTimeUsed - runTimeChange,
                    usageStats.lastTimeUsed,
                    runTimeChange
                )
                list.add(info)
                Log.d(TAG, """
                            >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                            ${info.packageName}
                            启动时间: ${LocalDateTime.ofInstant(Instant.ofEpochMilli(usageStats.lastTimeUsed - runTimeChange),
                    ZoneId.systemDefault()).format(
                    DateTimeFormatter.ISO_DATE_TIME)}
                            结束时间：${LocalDateTime.ofInstant(Instant.ofEpochMilli(info.endTime),
                    ZoneId.systemDefault()).format(
                    DateTimeFormatter.ISO_DATE_TIME)}
                            使用时间: ${info.runTime/1000}
                        """.trimIndent())
                baseUsageStatsMap[usageStats.packageName] = usageStats
            }
            if (list.isNotEmpty()){
                ioExecutorService.submit{
                    getAppDataBase().getUseStateDao().insertAll(list)
                }
            }
            lastUsageStatsMap[usageStats.packageName] = usageStats
        }
    }

    private fun registerBroadcastReceiver() {
        registerReceiver(batteryChangerReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
        //屏幕状态，检测是否睡眠
        val screenFilter = IntentFilter(Intent.ACTION_SCREEN_ON)
        screenFilter.addAction(Intent.ACTION_SCREEN_OFF)
        registerReceiver(screenChangeReceiver, screenFilter)
    }

    override fun onDestroy() {
        unregisterReceiver(batteryChangerReceiver)
        unregisterReceiver(screenChangeReceiver)
        super.onDestroy()
    }

}